/**
 * 错误处理和异常监控工具
 */

import { ElMessage, ElNotification } from 'element-plus'

// 错误类型枚举
export const ErrorTypes = {
  NETWORK_ERROR: 'NETWORK_ERROR',
  API_ERROR: 'API_ERROR',
  VALIDATION_ERROR: 'VALIDATION_ERROR',
  PERMISSION_ERROR: 'PERMISSION_ERROR',
  BUSINESS_ERROR: 'BUSINESS_ERROR',
  SYSTEM_ERROR: 'SYSTEM_ERROR',
  UNKNOWN_ERROR: 'UNKNOWN_ERROR'
}

// 错误级别枚举
export const ErrorLevels = {
  LOW: 'low',
  MEDIUM: 'medium',
  HIGH: 'high',
  CRITICAL: 'critical'
}

// 错误信息配置
const errorConfig = {
  [ErrorTypes.NETWORK_ERROR]: {
    title: '网络错误',
    message: '网络连接异常，请检查网络设置',
    level: ErrorLevels.HIGH,
    showNotification: true,
    showMessage: true
  },
  [ErrorTypes.API_ERROR]: {
    title: '接口错误',
    message: '服务器响应异常，请稍后重试',
    level: ErrorLevels.MEDIUM,
    showNotification: true,
    showMessage: true
  },
  [ErrorTypes.VALIDATION_ERROR]: {
    title: '数据验证错误',
    message: '输入数据格式不正确',
    level: ErrorLevels.LOW,
    showNotification: false,
    showMessage: true
  },
  [ErrorTypes.PERMISSION_ERROR]: {
    title: '权限不足',
    message: '您没有执行此操作的权限',
    level: ErrorLevels.MEDIUM,
    showNotification: true,
    showMessage: true
  },
  [ErrorTypes.BUSINESS_ERROR]: {
    title: '业务错误',
    message: '业务逻辑处理失败',
    level: ErrorLevels.MEDIUM,
    showNotification: true,
    showMessage: true
  },
  [ErrorTypes.SYSTEM_ERROR]: {
    title: '系统错误',
    message: '系统内部错误，请联系管理员',
    level: ErrorLevels.CRITICAL,
    showNotification: true,
    showMessage: true
  },
  [ErrorTypes.UNKNOWN_ERROR]: {
    title: '未知错误',
    message: '发生未知错误，请稍后重试',
    level: ErrorLevels.HIGH,
    showNotification: true,
    showMessage: true
  }
}

// 错误日志存储
class ErrorLogger {
  constructor() {
    this.errors = []
    this.maxErrors = 1000 // 最大存储错误数量
  }

  // 添加错误日志
  addError(error) {
    const errorLog = {
      id: Date.now() + Math.random(),
      timestamp: new Date().toISOString(),
      type: error.type || ErrorTypes.UNKNOWN_ERROR,
      level: error.level || ErrorLevels.MEDIUM,
      message: error.message || '未知错误',
      stack: error.stack || '',
      url: error.url || window.location.href,
      userAgent: navigator.userAgent,
      userId: error.userId || null,
      sessionId: error.sessionId || null,
      extra: error.extra || {}
    }

    this.errors.unshift(errorLog)

    // 限制错误数量
    if (this.errors.length > this.maxErrors) {
      this.errors = this.errors.slice(0, this.maxErrors)
    }

    // 发送到服务器（实际项目中应该发送到日志服务器）
    this.sendToServer(errorLog)

    return errorLog
  }

  // 获取错误日志
  getErrors(filter = {}) {
    let filteredErrors = [...this.errors]

    if (filter.type) {
      filteredErrors = filteredErrors.filter(error => error.type === filter.type)
    }

    if (filter.level) {
      filteredErrors = filteredErrors.filter(error => error.level === filter.level)
    }

    if (filter.startTime && filter.endTime) {
      filteredErrors = filteredErrors.filter(error => {
        const errorTime = new Date(error.timestamp)
        return errorTime >= new Date(filter.startTime) && errorTime <= new Date(filter.endTime)
      })
    }

    return filteredErrors
  }

  // 清空错误日志
  clearErrors() {
    this.errors = []
  }

  // 发送错误到服务器
  sendToServer(errorLog) {
    // 实际项目中应该发送到日志服务器
    console.log('发送错误日志到服务器:', errorLog)
  }
}

// 创建错误日志实例
const errorLogger = new ErrorLogger()

// 错误处理类
class ErrorHandler {
  constructor() {
    this.setupGlobalErrorHandlers()
  }

  // 设置全局错误处理器
  setupGlobalErrorHandlers() {
    // 捕获未处理的Promise错误
    window.addEventListener('unhandledrejection', (event) => {
      this.handleError({
        type: ErrorTypes.SYSTEM_ERROR,
        level: ErrorLevels.HIGH,
        message: `Unhandled Promise Rejection: ${event.reason}`,
        stack: event.reason?.stack || '',
        extra: { reason: event.reason }
      })
    })

    // 捕获全局JavaScript错误
    window.addEventListener('error', (event) => {
      this.handleError({
        type: ErrorTypes.SYSTEM_ERROR,
        level: ErrorLevels.HIGH,
        message: event.message,
        stack: event.error?.stack || '',
        extra: {
          filename: event.filename,
          lineno: event.lineno,
          colno: event.colno
        }
      })
    })
  }

  // 处理错误
  handleError(error) {
    // 记录错误日志
    const errorLog = errorLogger.addError(error)

    // 获取错误配置
    const config = errorConfig[error.type] || errorConfig[ErrorTypes.UNKNOWN_ERROR]

    // 显示错误消息
    if (config.showMessage) {
      ElMessage.error(config.message)
    }

    // 显示错误通知
    if (config.showNotification) {
      ElNotification({
        title: config.title,
        message: config.message,
        type: this.getNotificationType(error.level),
        duration: this.getNotificationDuration(error.level),
        position: 'top-right'
      })
    }

    // 如果是严重错误，记录到控制台
    if (error.level === ErrorLevels.CRITICAL) {
      console.error('严重错误:', errorLog)
    }

    return errorLog
  }

  // 处理API错误
  handleApiError(response, request) {
    let errorType = ErrorTypes.API_ERROR
    let message = '请求失败'

    if (!response) {
      errorType = ErrorTypes.NETWORK_ERROR
      message = '网络连接失败'
    } else if (response.status === 401) {
      errorType = ErrorTypes.PERMISSION_ERROR
      message = '登录已过期，请重新登录'
    } else if (response.status === 403) {
      errorType = ErrorTypes.PERMISSION_ERROR
      message = '权限不足'
    } else if (response.status === 404) {
      errorType = ErrorTypes.API_ERROR
      message = '请求的资源不存在'
    } else if (response.status >= 500) {
      errorType = ErrorTypes.SYSTEM_ERROR
      message = '服务器内部错误'
    } else if (response.data?.message) {
      message = response.data.message
    }

    return this.handleError({
      type: errorType,
      level: this.getErrorLevel(response?.status),
      message,
      stack: '',
      extra: {
        status: response?.status,
        url: request?.url,
        method: request?.method,
        data: request?.data
      }
    })
  }

  // 处理验证错误
  handleValidationError(errors) {
    const errorMessages = Array.isArray(errors) ? errors : [errors]
    
    errorMessages.forEach(error => {
      this.handleError({
        type: ErrorTypes.VALIDATION_ERROR,
        level: ErrorLevels.LOW,
        message: error.message || error,
        stack: '',
        extra: { field: error.field }
      })
    })
  }

  // 处理业务错误
  handleBusinessError(message, extra = {}) {
    return this.handleError({
      type: ErrorTypes.BUSINESS_ERROR,
      level: ErrorLevels.MEDIUM,
      message,
      stack: '',
      extra
    })
  }

  // 获取通知类型
  getNotificationType(level) {
    const typeMap = {
      [ErrorLevels.LOW]: 'info',
      [ErrorLevels.MEDIUM]: 'warning',
      [ErrorLevels.HIGH]: 'error',
      [ErrorLevels.CRITICAL]: 'error'
    }
    return typeMap[level] || 'error'
  }

  // 获取通知持续时间
  getNotificationDuration(level) {
    const durationMap = {
      [ErrorLevels.LOW]: 3000,
      [ErrorLevels.MEDIUM]: 5000,
      [ErrorLevels.HIGH]: 8000,
      [ErrorLevels.CRITICAL]: 0 // 不自动关闭
    }
    return durationMap[level] || 5000
  }

  // 根据HTTP状态码获取错误级别
  getErrorLevel(status) {
    if (!status) return ErrorLevels.HIGH
    
    if (status >= 500) return ErrorLevels.CRITICAL
    if (status >= 400) return ErrorLevels.MEDIUM
    return ErrorLevels.LOW
  }

  // 获取错误统计
  getErrorStats() {
    const errors = errorLogger.getErrors()
    const stats = {
      total: errors.length,
      byType: {},
      byLevel: {},
      recent: errors.slice(0, 10)
    }

    errors.forEach(error => {
      // 按类型统计
      stats.byType[error.type] = (stats.byType[error.type] || 0) + 1
      
      // 按级别统计
      stats.byLevel[error.level] = (stats.byLevel[error.level] || 0) + 1
    })

    return stats
  }

  // 清空错误日志
  clearErrors() {
    errorLogger.clearErrors()
  }
}

// 创建错误处理实例
const errorHandler = new ErrorHandler()

// 错误处理装饰器
export function withErrorHandling(target, propertyKey, descriptor) {
  const originalMethod = descriptor.value

  descriptor.value = async function (...args) {
    try {
      return await originalMethod.apply(this, args)
    } catch (error) {
      errorHandler.handleError({
        type: ErrorTypes.SYSTEM_ERROR,
        level: ErrorLevels.MEDIUM,
        message: error.message || '方法执行失败',
        stack: error.stack || '',
        extra: {
          method: `${target.constructor.name}.${propertyKey}`,
          arguments: args
        }
      })
      throw error
    }
  }

  return descriptor
}

// API请求错误处理装饰器
export function withApiErrorHandling(target, propertyKey, descriptor) {
  const originalMethod = descriptor.value

  descriptor.value = async function (...args) {
    try {
      return await originalMethod.apply(this, args)
    } catch (error) {
      errorHandler.handleApiError(error.response, error.request)
      throw error
    }
  }

  return descriptor
}

// 导出错误处理实例和相关工具
export { errorHandler, errorLogger }

// 导出默认错误处理实例
export default errorHandler
